package excel

import (
	"errors"
	"fmt"
	"log"

	s "gitee.com/xiaoa7/jsetl/service"
	jsvmcore "gitee.com/xiaoa7/jsvm-core"
	"github.com/dop251/goja"
)

var (
	colNames = []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
)

// 获取数据库实例
func getInstance(id string) (*Excel, error) {
	if ins := s.GetService(id); ins != nil {
		if _redis, ok := ins.(*Excel); ok {
			return _redis, nil
		} else {
			return nil, errors.New("Excel instance type error")
		}
	}
	return nil, errors.New("can't find excel instance")
}

// 保存
func (e *Excel) save() {
	if e.file != nil {
		e.file.Save()
	}
}

// 生成当前sheet的字段映射
func (e *Excel) genColMappings(sheet string) {
	if _, ok := e.SheetColMappinges[sheet]; ok {
		return
	}
	cm := &SheetColMapping{make(map[string]string), make(map[string]int), make(map[int]string)}
	e.SheetColMappinges[sheet] = cm
	//读取第一行
	if rs, err := e.file.Rows(sheet); err == nil {
		rs.Next()
		cols, _ := rs.Columns()
		for i, c := range cols {
			cm.fieldMapping[c] = colNames[i]
			cm.fieldColName2IndexMapping[c] = i
			cm.fieldIndex2ColNameMapping[i] = c
		}
		rs.Close()
	}
}

// 读数据
func (e *Excel) read(sheet string, startRow, endRow int) []map[string]string {
	e.genColMappings(sheet)
	cm := e.SheetColMappinges[sheet]
	ret := make([]map[string]string, 0)
	log.Println(cm.fieldMapping)
	if rs, err := e.file.Rows(sheet); err == nil {
		for index := 0; rs.Next() && index < endRow; index++ {
			if index < startRow {
				continue
			} else if index >= endRow {
				break
			}
			row := map[string]string{}
			cols, _ := rs.Columns()
			for colIndex, c := range cols {
				row[cm.fieldIndex2ColNameMapping[colIndex]] = c
			}
			ret = append(ret, row)
		}
		rs.Close()
	}
	return ret
}

// 写入数据
func (e *Excel) write(sheet string, row int, data map[string]string) error {
	e.genColMappings(sheet)
	cm := e.SheetColMappinges[sheet]
	for k, v := range data {
		if colName, ok := cm.fieldMapping[k]; ok {
			e.file.SetCellValue(sheet, fmt.Sprintf("%s%d", colName, row), v)
		}
	}
	return nil
}

// 初始化
func init() {
	jsvmcore.RegisterObject("excel", map[string]jsvmcore.HandleFn{
		//打开excel文件
		"open": func(vm *jsvmcore.JsVM) jsvmcore.JsVmFn {
			return func(params ...interface{}) goja.Value {
				if len(params) < 2 {
					return vm.State.ToValue("无效的输入参数")
				}
				excelInstance, _ := params[0].(string)
				filePath, _ := params[1].(string)
				if err := OpenExcelFile(excelInstance, filePath); err == nil {
					return vm.State.ToValue("ok")
				} else {
					return vm.State.ToValue(err.Error())
				}
			}
		},
		//读取数据
		"read": func(vm *jsvmcore.JsVM) jsvmcore.JsVmFn {
			return func(params ...interface{}) goja.Value {
				if len(params) < 3 {
					return vm.State.ToValue("无效的输入参数")
				}
				excelInstance, _ := params[0].(string)
				sheet, _ := params[1].(string)
				start, _ := params[2].(int64)
				end, _ := params[3].(int64)
				if ins, err := getInstance(excelInstance); err == nil {
					ret := ins.read(sheet, int(start), int(end))
					return vm.State.ToValue(ret)
				} else {
					return vm.State.ToValue(err.Error())
				}
			}
		},
		//写入数据
		"write": func(vm *jsvmcore.JsVM) jsvmcore.JsVmFn {
			return func(params ...interface{}) goja.Value {
				if len(params) < 3 {
					return vm.State.ToValue("无效的输入参数")
				}
				excelInstance, _ := params[0].(string)
				sheet, _ := params[1].(string)
				rowIndex, _ := params[2].(int64)
				data, _ := params[3].(map[string]interface{})
				_data := map[string]string{}
				for k, v := range data {
					_data[k], _ = v.(string)
				}
				if ins, err := getInstance(excelInstance); err == nil {
					if err = ins.write(sheet, int(rowIndex), _data); err != nil {
						return vm.State.ToValue(err.Error())
					} else {
						return vm.State.ToValue("ok")
					}
				} else {
					return vm.State.ToValue(err.Error())
				}
			}
		},
		//退出前，保存数据
		"save": func(vm *jsvmcore.JsVM) jsvmcore.JsVmFn {
			return func(params ...interface{}) goja.Value {
				if len(params) < 1 {
					return vm.State.ToValue("无效的输入参数")
				}
				excelInstance, _ := params[0].(string)
				if ins, err := getInstance(excelInstance); err == nil {
					ins.save()
				}
				return vm.State.ToValue("ok")
			}
		},
	})
}
